/**
 * @author 吴宇亮
 * @describe framework.js 内置了一些常用的方法 和 初始化新打开页面获取当前页面的主题颜色
 * @date 2018-12-19
 */
$(function(){
    //初始化查询和重置功能，custom为自定义查询
    $(".search_btn:not(.custom)").on("click", function() {
        reloadTable();
    });
    $(".reset_btn:not(.custom)").on("click", function() {
        $('#_form')[0].reset();
        setTimeout(reloadTable, 100);
    });

    //监听回车事件：回车搜索
    document.onkeydown = function (event) {
        let e = event || window.event;
        if (e && e.keyCode == 13 && $("#_form").length > 0) { //回车键的键值为13 且 为主页面，回车才触发查询
            reloadTable();
        }
    };

});

/**
 * 默认用id为_form的表单刷新id为_table的table.兼容本页面的table刷新 和 弹窗之后父页面table的刷新.
 */
function reloadTable(tableId, formId){
    tableId = tableId || "_table";
    formId = formId || "_form";

    if(layui.table && layui.table.cache[tableId]){
        layui.table.reload(tableId, {
            where : serializeObject($(`#${formId}`))
        });
    }else if(parent.layui.table && parent.layui.table.cache[tableId]){
        parent.layui.table.reload(tableId, {
            where : serializeObject($(`#${formId}`))
        });
    }
}

function reloadTreeGrid(treeGrid, tableId, formId){
    tableId = tableId || "_table";
    formId = formId || "_form";

    treeGrid.reload(tableId, {
        where : serializeObject($(`#${formId}`))
    });
}

/**
 * 发起ajax请求，可以用于送审、审批、删除等操作 <br/>
 *
 * @param url 请求路径 <br/>
 * @param requestObj 请求参数对象，如：{lid : 主键} <br/>
 * @param jsonSetting jsonSetting为json对象，它里面有两个属性：<br/>
 *          refreshedTableId 请求成功后刷新id为refreshedTableId的table，默认为_table <br/>
 *          refreshedFormId 请求成功后用id为refreshedFormId的form提交表单，默认为_form <br/>
 * @param treeGrid 如果要刷新的是treeTable，则要传入treeTable的id；如果要刷新的是table，则无需传入
 */
var oldUuid = null;
function ajax(url, requestObj, jsonSetting, treeGrid){
    let newUuid = frameworkUuid;
    if(oldUuid == newUuid){
        return layer.msg("请勿重复提交",{icon:2});
    }else{
        oldUuid = newUuid;
    }

    let shade = parent.layer.msg('数据提交中', {icon: 16, shade: 0.3, time:5000});//显示模态框，考虑用户体验，即使后台没返回信息，5秒钟后也自动关闭
    $.post(__ctxPath + url, requestObj, function(response){
        parent.layer.close(shade);
        if(response.code != RESPONSE_SUCCESS){
            //TODO，根据后台的弹窗方式来进行提示
            response.msg ? parent.layer.msg(response.msg,{icon:2}) : parent.layer.msg("操作失败",{icon:2});
            clearRepeatCommitCheck();
            return;
        }

        response.msg ? layer.msg(response.msg,{icon:1}) : layer.msg("操作成功",{icon:1});
        if(window.name){//弹窗页面方式的关闭
            var index = parent.layer.getFrameIndex(window.name);
            if(index){
                parent.layer.close(index);
                parent.layer.msg(response.msg,{icon:1});
            }
        }

        jsonSetting = jsonSetting || {};
        if(treeGrid){
            reloadTreeGrid(treeGrid, jsonSetting.refreshedTableId, jsonSetting.refreshedFormId)
        }else{
            reloadTable(jsonSetting.refreshedTableId, jsonSetting.refreshedFormId);
        }
    }, "json");
}

/**
 * 清除重复提交校验
 */
function clearRepeatCommitCheck(){
    oldUuid = null;
}

/**
 * 发起get请求
 *
 * @param url 请求路径
 * @param requestParam 请求参数，json格式
 *
 * 使用方法:
 * getJSON("/Upload.do?method=deleteFile&sysFileLid=1").then(resp => {console.log(resp)}.catch(err => { console.error(err) });
 *
 * 参考博客：https://blog.csdn.net/lck8989/article/details/80354784
 */
function _get(url, requestParam) {
    url = serializeRequestParam(url, requestParam);
    return new Promise(function(resolve, reject) {
        let XHR = new XMLHttpRequest();
        XHR.open('GET', url, true);
        XHR.send();

        XHR.onreadystatechange = function() {
            if (XHR.readyState == 4) {
                if (XHR.status == 200) {
                    try {
                        var response = JSON.parse(XHR.responseText);
                        resolve(response);
                    } catch (e) {
                        reject(e);
                    }
                } else {
                    reject(new Error(XHR.statusText));
                }
            }
        }
    })
}

function _post(url, requestParam) {
    url = serializeRequestParam(url, requestParam);
    return new Promise(function(resolve, reject) {
        let XHR = new XMLHttpRequest();
        XHR.open('POST', url, true);
        XHR.send();

        XHR.onreadystatechange = function() {
            if (XHR.readyState == 4) {
                if (XHR.status == 200) {
                    try {
                        var response = JSON.parse(XHR.responseText);
                        resolve(response);
                    } catch (e) {
                        reject(e);
                    }
                } else {
                    reject(new Error(XHR.statusText));
                }
            }
        }
    })
}


/**
 * 跳转到指定页面 <br/>
 *
 * @example 示例：toPage("/assit/caseInfo.do?method=toEdit", {"lid": data.lid, "pageUrl": "business/assit/case/caseManager/jsp/update"}, [[ '按钮名称', '选择器'], ['按钮名称', '选择器']...]); <br/>
 * @param url 跳转的页面的url <br/>
 * @param requestObj {pageType:弹出页的类型 ,title：弹出页标题（默认为'新增'），width：弹出页宽度（默认为'80%'），height：弹出页高度（默认为'80%'）} <br/>
 * @param btnArr 自定义按钮，[[ '按钮名称', '选择器'], ['按钮名称', '选择器']...]。注意，如果使用自定义按钮，得在目标弹出层中有相应的隐藏按钮
 */
function toPage(url, requestObj, btnArr){
    if(!url){
        layui.layer.msg('请指定跳转的url地址', {icon: 2});
        return;
    }

    requestObj = requestObj || {};
    let width = requestObj.width || "80%"
        ,height = requestObj.height || "80%"
        ,pageType = requestObj.pageType || TO_ADD;
    let title = "信息";
    if(pageType == TO_ADD){
        title = requestObj.title || "新增";
    }else if(pageType == TO_EDIT){
        title = requestObj.title || "修改";
    }else if(pageType == TO_VIEW){
        title = requestObj.title || "查看";
    }

    //构造layer.open参数
    var layerParam = {
        title : title
        ,type : 2
        ,maxmin: true
        ,area : [ width, height ]
    };

    //构造请求路径
    if(url.indexOf(".do") > -1){ //如果自带了.do，说明是 跳转到修改或者查看明细 等页面，需要携带请求参数即可
        layerParam.content = serializeRequestParam(__ctxPath + url, requestObj);
    }else{ //如果没有.do，就说明是单纯的跳转页面，不需要携带请求参数
        //layerParam.content = __ctxPath + "/Url.do?method=toPage&url=" + url;
        layerParam.content = serializeRequestParam(__ctxPath + "/Url.do?method=toPage&url=" + url, requestObj);
    }

    //如果有自定义按钮
    if(btnArr){
        layerParam.btn = [];
        for(var i = 0; i < btnArr.length; i++){
            layerParam.btn.push(btnArr[i][0]);
            _addClickListener(layerParam, btnArr, i);
        }
        layerParam.btn.push('取消');
        layerParam['btn' + layerParam.btn.length] = function(index, layero){
            return _closeLayer(layero); //如果return false则不会关闭页面
        }

    //如果是新增或者修改就有提交按钮和取消按钮
    }else if(pageType == TO_ADD || pageType == TO_EDIT){
        layerParam.btn = ['提交', '取消'];
        layerParam.btn1 = function(index, layero){ //按钮【提交】的回调函数, layero当前层DOM；index当前层索引
            let iframeWin = window[layero.find('iframe')[0]['name']]; //得到iframe页的窗口对象。可以用来执行iframe页的方法：iframeWin.method();
            $(iframeWin.document).find(".form-submit-btn").click();

            return false; //开启该代码可禁止点击该按钮关闭当前弹出层
        }
        layerParam.btn2 = function(index, layero){//按钮【取消】的回调, layero当前层DOM；index当前层索引
            return _closeLayer(layero); //如果return false则不会关闭页面
        }

     //查看只有关闭按钮
    }else if(pageType == TO_VIEW){
        layerParam.btn = ['关闭'];
    }

    //layer弹出层加载完毕的回调函数。layero当前层DOM；index当前层索引
    layerParam.success = function(layero, index){
        //暂时空实现，以后框架有需要可以定义回调
    };
    //右上角关闭按钮触发的回调
    layerParam.cancel = function(index, layero){
        return _closeLayer(layero); //如果return false则不会关闭页面
    }

    var index = layui.layer.open(layerParam);
    layer.iframeAuto(index);

    window.event? window.event.cancelBubble = true : e.stopPropagation();
}

function _closeLayer(layero){
    let iframeWin = window[layero.find('iframe')[0]['name']]; //得到iframe页的窗口对象。可以用来执行iframe页的方法：iframeWin.method();
    let result = true;
    if(typeof iframeWin.closeLayer === "function") {
        eval("result = iframeWin.closeLayer();");
    }
    return result;
}

//提取出来是因为要解决 js循环加载监听事件的闭包问题，参考博客：https://blog.csdn.net/playboyanta123/article/details/17241597
function _addClickListener(layerParam, btnArr, i){
    layerParam[`btn${i+1}`] = function(index, layero){
        let iframeWin = window[layero.find('iframe')[0]['name']]; //得到iframe页的窗口对象。可以用来执行iframe页的方法：iframeWin.method();
        $(iframeWin.document).find(btnArr[i][1]).click();
        return false; //开启该代码可禁止点击该按钮关闭当前弹出层
    }
}

/**
 * 获取layui的table所选项的lid，并且默认以","分隔。通常可以用作批量操作 <br/>
 *
 * @example 示例：
 *
 * @param tableId table的lay-filter <br/>
 * @param idFieldName id字段名称，默认为lid <br/>
 * @param sperator 分隔符，默认为"," <br/>
 */
function getLidsOfSelections(tableId, idFieldName, sperator){
    idFieldName = idFieldName || "lid";
    sperator = sperator || ",";

    var rows = layui.table.checkStatus(tableId).data; //获取选中行的数据
    var lids = "";
    for(var i = 0; i < rows.length; i++){
        if(i != rows.length-1){
            lids += getJsonValue(rows[i], idFieldName) + sperator;
        }else{
            lids += getJsonValue(rows[i], idFieldName);
        }
    }
    return lids;
}

/**
 *  获取当前时间，格式YYYY-MM-DD <br/>
 *
 *  @param seperator1 分隔符 <br/>
 */
function getNowDate(seperator1) {
    seperator1 = seperator1 || "-";

    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var strDate = date.getDate();
    if (month >= 1 && month <= 9) {
        month = "0" + month;
    }
    if (strDate >= 0 && strDate <= 9) {
        strDate = "0" + strDate;
    }
    var currentdate = year + seperator1 + month + seperator1 + strDate;
    return currentdate;
}

/**
 *  给定两个字符串日期，获取它们之间相隔的天数 <br/>
 *
 *  @param strDateStart 开始日期 <br/>
 *  @param strDateEnd 结束日期 <br/>
 *  @param separator 分隔符 <br/>
 */
function getDays(strDateStart, strDateEnd, separator){
    separator = separator || "-";

    var oDate1= strDateStart.split(separator);
    var oDate2= strDateEnd.split(separator);
    var strDateS = new Date(oDate1[0], oDate1[1]-1, oDate1[2]);
    var strDateE = new Date(oDate2[0], oDate2[1]-1, oDate2[2]);
    return parseInt(Math.abs(strDateS - strDateE ) / 1000 / 60 / 60 /24)//把相差的毫秒数转换为天数
}

/**
 * 将json对象序列化 key1=value1&key2=value2的格式，并且拼接到url后，以提交到后台。 <br/>
 * 注意：requestObj里面的 <b>pageType、title、width、height</b> 这些属性不会序列化成请求参数！因为这这些属性是toDetail、toEdit等接口的关键字。<br/>
 * 如果因为业务特别需要这些属性，需手工带在url后面。
 *
 * @param url 原本的请求url <br/>
 * @param requestObj 带序列化的json对象 <br/>
 * @return url&key1=value1&key2=value2
 */
function serializeRequestParam(url, requestObj){
    if(!requestObj){
        return url;
    }

    //说明，对于数组，那么key为下标，value为下标对应的值；对于对象，那么key为键，value为值
    let isHasRequestParma = url.includes("?") ? true : false
        ,result = url;
    $.each(requestObj, function (key, value) {
        if(key != "pageType" && key != "title" && key != "width" && key != "height"){
            if(isHasRequestParma){
                result += `&${key}=${value}`;
            }else{
                result += `?${key}=${value}`;
                isHasRequestParma = true;
            }
        }
    });
    return result;
}

/**
 * 将form表单序列化成json对象 <br/>
 * 参考博客：https://www.cnblogs.com/exmyth/p/6947515.html <br/>
 *
 * @param obj 可以为form表单对象，也可以为可序列化为数组的对象 <br/>
 */
function serializeObject(obj) {
    var o = {};
    if(!obj) return o;

    var a = obj.serializeArray();
    $.each(a, function() {
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [ o[this.name] ];
            }
            o[this.name].push(this.value || '');
        } else if(this.name && this.name != 'undefined'){
            o[this.name] = this.value || '';
        }
    });
    return o;
}

/**
 * 通过字符串的方式去获取json对象的值 <br/>
 * 参考博客：https://www.cnblogs.com/exmyth/p/6947515.html <br/>
 * 示例： <br/>
 * const obj = { a: { b: 2 } }  <br/>
 * console.log( getJsonValue( obj, 'a.b' ) )    //输出2 <br/>
 *
 * @param obj 可以为form表单对象，也可以为可序列化为数组的对象 <br/>
 * @param path 属性的路径
 */
function getJsonValue( obj, path ) {
    return path.split( '.' ).reduce( ( target, key ) => target[ key ], obj ) //IE不支持
//     return path.split( '.' ).reduce( function (target, key){ return target[key]}, obj )
}

/**
 * 根据cookie的key去获取value
 */
function getCookie(name){
    let cookieArr = document.cookie.split("; "); //分割
    //遍历匹配
    for (let i = 0; i < cookieArr.length; i++) {
        let arr = cookieArr[i].split("=");
        if (arr[0] == name){
            if(arr[1].startsWith("\"")){
                return arr[1].substring(1, arr[1].length-1);
            }else{
                return arr[1];
            }
        }
    }
    return "";
}

/**
 * 添加cookie。此 cookie 将被保存 30 天
 * @param name cookie名字
 * @param value 值
 */
function setCookie(name,value){
    let Days = 30;
    let exp = new Date();
    exp.setTime(exp.getTime() + Days*24*60*60*1000);
    document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
}


/**
 * 删除cookie
 * @param name cookie名字
 */
function delCookie(name) {
    let exp = new Date();
    exp.setTime(exp.getTime() - 1);
    let cval = getCookie(name);
    if (cval != null) {
        // 这里删除操作其实是将expires过期时间设置为当前时间，使cookie立即过期
        document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
    }
}
